/** \file    shell.cpp
  * \brief   Facilities to register file associations in Windows shell.
  * \date    2003
  * \author  Fedor Chelnokov
  * \version $Header: /home/cscom1r4/cvsroot/cs/mswin/src/shell.cpp,v 1.1 2004/01/23 21:29:35 cscom1r4 Exp $
  */

#include "mswin\shell.h"
#include "mswin\registry.h"
#include <Shlobj.h>

namespace mswin {

void AssociatePrimaryProgId(std::string Ext, const std::string & ProgId,
							const std::string & MIMEType)
{
	if (Ext.empty())
		return;
	if (Ext[0] != '.')
		Ext = std::string(".") + Ext;

	using namespace xml;
	xml::registry reg(HKEY_CLASSES_ROOT);

	node enode = reg.root().create(Ext);
	string OldProgId = enode[""].def(string());
	if (!MIMEType.empty())
		enode["Content Type"] = MIMEType;

	if (OldProgId != ProgId) {
		enode[""] = ProgId;
		if (!OldProgId.empty()) 
			enode.create("OpenWithProgids").create(OldProgId);
		SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
	}
}

std::string GetPrimaryProgId(std::string Ext)
{
	if (Ext.empty())
		return std::string();
	if (Ext[0] != '.')
		Ext = std::string(".") + Ext;

	using namespace xml;
	xml::registry reg(HKEY_CLASSES_ROOT);

	node enode = reg.root().child(Ext, node());
	if (enode.null())
		return std::string();

	return enode[""].def(string());
}

void AssociateSecondaryProgId(std::string Ext, const std::string & ProgId)
{
	if (Ext.empty())
		return;
	if (Ext[0] != '.')
		Ext = std::string(".") + Ext;

	using namespace xml;
	xml::registry reg(HKEY_CLASSES_ROOT);

	node enode = reg.root().create(Ext);
	string OldProgId = enode[""].def(string());

	if (OldProgId.empty()) {
		enode[""] = ProgId;
		SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
	} else if (OldProgId != ProgId) {
		node onode = enode.create("OpenWithProgids");
		if (onode.child(ProgId, node()).null()) {
			onode.create(ProgId);
			SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
		}
	}
}

void CancelProgIdAssociation(std::string Ext, const std::string & ProgId)
{
	if (Ext.empty())
		return;
	if (Ext[0] != '.')
		Ext = std::string(".") + Ext;

	using namespace xml;
	xml::registry reg(HKEY_CLASSES_ROOT);

	node enode = reg.root().child(Ext, node());
	if (enode.null())
		return;
	string OldProgId = enode[""].def(string());

	if (OldProgId == ProgId) {
		enode[""] = "";
		SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
	}

	node onode = enode.child("OpenWithProgids", node());
	if (!onode.null() && !onode.child(ProgId, node()).null()) {
		reg.erase(onode, ProgId);
		SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
	}
}

void SetProgIdDescriptionAndIcon(const std::string & ProgId, 
	const std::string & Desc, const std::string & Icon)
{
	using namespace xml;
	xml::registry reg(HKEY_CLASSES_ROOT);
	node pnode = reg.root().create(ProgId);
	pnode[""] = Desc;
	pnode.create("DefaultIcon")[""] = Icon;
}

void SetProgIdAction(const std::string & ProgId, const std::string & Command,
	const std::string & Verb, const std::string & Desc,	bool def)
{
	using namespace xml;
	xml::registry reg(HKEY_CLASSES_ROOT);

	node shell = reg.root().create(ProgId).create("Shell");
	if (def)
		shell[""] = Verb;

	node verb = shell.create(Verb);
	if (!Desc.empty())
		verb[""] = Desc;

	verb.create("command")[""] = Command;
}

} //namespace mswin
